package com.yunqiao.service.api.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunqiao.common.consts.AppConsts;
import com.yunqiao.common.exception.CustomApiException;
import com.yunqiao.common.utils.PageUtils;
import com.yunqiao.common.utils.Query;
import com.yunqiao.service.api.ApplyWithdrawService;
import com.yunqiao.service.api.entity.ApplyWithdrawEntity;
import com.yunqiao.service.api.entity.FundDetailEntity;
import com.yunqiao.service.api.entity.UserEntity;
import com.yunqiao.service.api.mapper.ApplyPartnerMapper;
import com.yunqiao.service.api.mapper.ApplyWithdrawMapper;
import com.yunqiao.service.api.mapper.FundDetailMapper;
import com.yunqiao.service.api.mapper.UserMapper;
import com.yunqiao.service.api.vo.ApplyWithdrawVo;
import com.yunqiao.service.sys.entity.SysUserEntity;
import com.yunqiao.service.sys.mapper.SysUserDao;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Map;


@Service("applyWithdrawService")
public class ApplyWithdrawServiceImpl extends ServiceImpl<ApplyWithdrawMapper, ApplyWithdrawEntity> implements ApplyWithdrawService {

    @Autowired
    private ApplyWithdrawMapper applyWithdrawMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private ApplyPartnerMapper applyPartnerMapper;
    @Autowired
    private FundDetailMapper fundDetailMapper;

    /**
     * 用户司机提现
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        //各种查询条件的过滤,在此进行
        QueryWrapper<ApplyWithdrawEntity> queryWrapper = new QueryWrapper<>();
        // 用户司机提现申请
        queryWrapper.eq("a.type", AppConsts.WITHDRAW_TYPE_1);
        if (params.get("status") != null) {
            queryWrapper.eq("status", params.get("status"));
        }


        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "province"))) {
            queryWrapper.eq("u.province", MapUtil.getStr(params, "province"));
        }

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "city"))) {
            queryWrapper.eq("u.city", MapUtil.getStr(params, "city"));
        }

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "district"))) {
            queryWrapper.eq("u.district", MapUtil.getStr(params, "district"));
        }

        if (params.get("state") != null && StringUtils.isNotEmpty(MapUtil.getStr(params, "state"))) {
            queryWrapper.eq("a.state", MapUtil.getStr(params, "state"));
        }

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "createTime")) && StringUtils.isNotEmpty(MapUtil.getStr(params, "updateTime"))) {
            //当开始时间用
            queryWrapper.between("a.create_time", DateUtil.parse(MapUtil.getStr(params, "createTime"), "yyyy-MM-dd"), DateUtil.parse(MapUtil.getStr(params, "updateTime"), "yyyy-MM-dd"));
        }
        IPage<ApplyWithdrawVo> page = this.applyWithdrawMapper.pageList(new Query<ApplyWithdrawEntity>(params).getPage(), queryWrapper);
        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPagePartner(Map<String, Object> params) {
        //各种查询条件的过滤,在此进行
        QueryWrapper<ApplyWithdrawEntity> queryWrapper = new QueryWrapper<>();
        // 用户司机提现申请
        SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
        queryWrapper.eq("u.user_id", user.getUserId());
        queryWrapper.eq("a.type", AppConsts.WITHDRAW_TYPE_2);
        queryWrapper.eq("a_p.state", AppConsts.USER_APPLY_PARTNER_STATE_3);

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "province"))) {
            queryWrapper.eq("a_p.province", MapUtil.getStr(params, "province"));
        }

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "city"))) {
            queryWrapper.eq("a_p.city", MapUtil.getStr(params, "city"));
        }

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "district"))) {
            queryWrapper.eq("a_p.district", MapUtil.getStr(params, "district"));
        }

        if (params.get("state") != null && StringUtils.isNotEmpty(MapUtil.getStr(params, "state"))) {
            queryWrapper.eq("a.state", MapUtil.getStr(params, "state"));
        }

        if (StringUtils.isNotEmpty(MapUtil.getStr(params, "createTime")) && StringUtils.isNotEmpty(MapUtil.getStr(params, "updateTime"))) {
            //当开始时间用
            queryWrapper.between("a.create_time", DateUtil.parse(MapUtil.getStr(params, "createTime"), "yyyy-MM-dd"), DateUtil.parse(MapUtil.getStr(params, "updateTime"), "yyyy-MM-dd"));
        }

        IPage<ApplyWithdrawVo> page = this.applyWithdrawMapper.pageListPartner(new Query<ApplyWithdrawEntity>(params).getPage(), queryWrapper);
        return new PageUtils(page);
    }

    @Override
    public ApplyWithdrawVo details(Long id) {
        return this.applyWithdrawMapper.details(id);
    }

    @Override
    public ApplyWithdrawVo detailsPartner(Long id) {
        return this.applyWithdrawMapper.detailsPartner(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(ApplyWithdrawEntity applyWithdrawEntity) {
        if (ObjectUtil.isNull(applyWithdrawEntity.getUserId()) || ObjectUtil.isNull(applyWithdrawEntity.getAmount()) || ObjectUtil.isNull(applyWithdrawEntity.getState())) {
            throw new CustomApiException("参数有误");
        }
        Integer count = applyWithdrawMapper.selectCount(new QueryWrapper<ApplyWithdrawEntity>()
            .eq("user_id", applyWithdrawEntity.getUserId())
            .eq("status", AppConsts.APPLY_WITHDRAW_1)
            .eq("type", AppConsts.WITHDRAW_TYPE_1)
        );
        if (count > 0) {
            throw new CustomApiException("你已经申请过了");
        }

        int i =0;
        do {
            //直到添加成功为止， 防止金额并发出现错误
            UserEntity userEntity = userMapper.selectById(applyWithdrawEntity.getUserId());
            if (ObjectUtil.isNull(userEntity)) {
                throw new CustomApiException("此用户不存在");
            }

            if (userEntity.getBalance().doubleValue() < AppConsts.APPLY_MIN_PRICE) {
                throw new CustomApiException("你的账户可用余额不足100元， 不能提现");
            }
            if (applyWithdrawEntity.getAmount().doubleValue() > userEntity.getBalance().doubleValue()) {
                throw new CustomApiException("你的账户可用余额为" + userEntity.getBalance() + "， 不足以提现，请降低提现金额");
            }
            //扣除用户总金额额  放到冻结金额中
            BigDecimal balance = userEntity.getBalance().subtract(applyWithdrawEntity.getAmount());
            BigDecimal blockBalance = userEntity.getBlockBalance().add(applyWithdrawEntity.getAmount());
            i = userMapper.updateBalance(userEntity.getId(), balance, blockBalance, userEntity.getVersion());
            //生成提现申请记录
            this.applyWithdrawMapper.insert(applyWithdrawEntity);
        } while (i==0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agree(Long id) {
        ApplyWithdrawEntity applyWithdrawEntity = applyWithdrawMapper.selectById(id);
        if (applyWithdrawEntity == null) {
            throw new RuntimeException("参数有误");
        }
        int i = 0;
        UserEntity userEntity = null;
        do {
            userEntity = userMapper.selectById(applyWithdrawEntity.getUserId());
            i = userMapper.updateBalance(userEntity.getId(),userEntity.getBalance(), userEntity.getBlockBalance().subtract(applyWithdrawEntity.getAmount()), userEntity.getVersion());
        }while (i == 0);
        //将状态改为已提现
        applyWithdrawEntity.setStatus(AppConsts.APPLY_WITHDRAW_2);
        applyWithdrawMapper.updateById(applyWithdrawEntity);
        //生成流水记录
        FundDetailEntity fundDetailEntity = new FundDetailEntity();
        fundDetailEntity.setRemark("提现");
        fundDetailEntity.setUserId(userEntity.getId().intValue());
        fundDetailEntity.setTypeChange(AppConsts.FUND_DETAIL_TYPE_2);
        fundDetailEntity.setRelateId(applyWithdrawEntity.getId().intValue());
        fundDetailEntity.setAmount(applyWithdrawEntity.getAmount());
        fundDetailMapper.insert(fundDetailEntity);
    }


    @Override
    public void refuse(Long id) {
        ApplyWithdrawEntity applyWithdrawEntity = applyWithdrawMapper.selectById(id);
        if (applyWithdrawEntity == null) {
            throw new RuntimeException("参数有误");
        }
        int i = 0;
        do {
            UserEntity userEntity = userMapper.selectById(applyWithdrawEntity.getUserId());
            i = userMapper.updateBalance(userEntity.getId(),userEntity.getBalance().add(applyWithdrawEntity.getAmount()), userEntity.getBlockBalance().subtract(applyWithdrawEntity.getAmount()), userEntity.getVersion());
        }while (i == 0);
        //将状态改为已拒绝
        applyWithdrawEntity.setStatus(AppConsts.APPLY_WITHDRAW_3);
        applyWithdrawMapper.updateById(applyWithdrawEntity);
    }

    @Override
    public void applyWithdraw(ApplyWithdrawEntity applyWithdrawEntity) {
        SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
        applyWithdrawEntity.setUserId(user.getUserId());
        applyWithdrawEntity.setType(AppConsts.WITHDRAW_TYPE_2);
        if (ObjectUtil.isNull(applyWithdrawEntity.getUserId()) || ObjectUtil.isNull(applyWithdrawEntity.getAmount()) || ObjectUtil.isNull(applyWithdrawEntity.getState())) {
            throw new CustomApiException("参数有误");
        }
        Integer count = applyWithdrawMapper.selectCount(new QueryWrapper<ApplyWithdrawEntity>()
            .eq("user_id", applyWithdrawEntity.getUserId())
            .eq("status", AppConsts.APPLY_WITHDRAW_1)
            .eq("type", AppConsts.WITHDRAW_TYPE_2)
        );
        if (count > 0) {
            throw new CustomApiException("你已经申请过了");
        }

        int i =0;
        do {
            //直到添加成功为止， 防止金额并发出现错误
            user = sysUserDao.selectById(user.getUserId());
            if (user.getBalance().doubleValue() < AppConsts.APPLY_MIN_PRICE) {
                throw new CustomApiException("你的账户可用余额不足100元， 不能提现");
            }
            if (applyWithdrawEntity.getAmount().doubleValue() > user.getBalance().doubleValue()) {
                throw new CustomApiException("你的账户可用余额为" + user.getBalance() + "， 不足以提现，请降低提现金额");
            }
            //扣除用户总金额额  放到冻结金额中
            BigDecimal balance = user.getBalance().subtract(applyWithdrawEntity.getAmount());
            BigDecimal blockBalance = user.getBlockBalance().add(applyWithdrawEntity.getAmount());
            i = sysUserDao.updateBalance(user.getUserId(), balance, blockBalance, user.getVersion());
            //生成提现申请记录
            this.applyWithdrawMapper.insert(applyWithdrawEntity);
        } while (i==0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreePartner(Long id) {
        ApplyWithdrawEntity applyWithdrawEntity = applyWithdrawMapper.selectById(id);
        if (applyWithdrawEntity == null) {
            throw new RuntimeException("参数有误");
        }
        int i = 0;
        SysUserEntity userEntity = null;
        do {
            userEntity = sysUserDao.selectById(applyWithdrawEntity.getUserId());
            i = sysUserDao.updateBalance(userEntity.getUserId(),userEntity.getBalance(), userEntity.getBlockBalance().subtract(applyWithdrawEntity.getAmount()), userEntity.getVersion());
        }while (i == 0);
        //将状态改为已提现
        applyWithdrawEntity.setStatus(AppConsts.APPLY_WITHDRAW_2);
        applyWithdrawMapper.updateById(applyWithdrawEntity);
        //生成流水记录
        FundDetailEntity fundDetailEntity = new FundDetailEntity();
        fundDetailEntity.setRemark("提现");
        fundDetailEntity.setUserId(userEntity.getUserId().intValue());
        fundDetailEntity.setTypeFrom(AppConsts.TYPE_FORM_1);
        fundDetailEntity.setTypeChange(AppConsts.FUND_DETAIL_TYPE_2);
        fundDetailEntity.setRelateId(applyWithdrawEntity.getId().intValue());
        fundDetailEntity.setAmount(applyWithdrawEntity.getAmount());
        fundDetailMapper.insert(fundDetailEntity);
    }

    @Override
    public void refusePartner(Long id) {
        ApplyWithdrawEntity applyWithdrawEntity = applyWithdrawMapper.selectById(id);
        if (applyWithdrawEntity == null) {
            throw new RuntimeException("参数有误");
        }
        int i = 0;
        do {
            SysUserEntity userEntity = sysUserDao.selectById(applyWithdrawEntity.getUserId());
            i = sysUserDao.updateBalance(userEntity.getUserId(),userEntity.getBalance().add(applyWithdrawEntity.getAmount()), userEntity.getBlockBalance().subtract(applyWithdrawEntity.getAmount()), userEntity.getVersion());
        }while (i == 0);
        //将状态改为已拒绝
        applyWithdrawEntity.setStatus(AppConsts.APPLY_WITHDRAW_3);
        applyWithdrawMapper.updateById(applyWithdrawEntity);
    }


}
